package net.sevear.chaos.p2p
{
	import com.douban.event.PlayCompleteEvent;
	import com.douban.event.PlayErrorEvent;
	import com.douban.event.PlayProgressEvent;
	import com.douban.media.AudioPlayer;
	import com.douban.media.DBRadio;
	import com.douban.utils.Format;
	
	import flash.events.EventDispatcher;
	import flash.net.SharedObject;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.utils.Dictionary;
	import flash.utils.setTimeout;
	
	import mx.collections.ArrayCollection;
	
	import net.sevear.chaos.event.ChaosSitesEvent;
	import net.sevear.chaos.event.ContactEvent;
	import net.sevear.chaos.event.p2p.P2pEvent;
	import net.sevear.chaos.event.p2p.P2pOffLineEvent;
	import net.sevear.chaos.recommend.ContactManager;
	import net.sevear.chaos.utils.Logger;
	import net.sevear.chaos.view.ChaosLogPanel;
	import net.sevear.chaos.vo.TrackInfo;
	import net.sevear.chaos.vo.UserInfo;

	public class P2PSitesManager extends EventDispatcher
	{
		private var _contactsSites:ArrayCollection;
		private var _curSiteID:int;
		private var curSite:P2PFMSiteClient;
		private var _siteConns:Dictionary;
		private var _running:Boolean;
		private var player:AudioPlayer;
		private var playList:ArrayCollection;
		private var logger:Logger = Logger.getInstance();
		private var curSong:TrackInfo;
		private var lastListenSiteID:int;
		private var isSendingLikeRequest:Boolean;
		private var dbLoader:URLLoader;
		private var so:SharedObject;
		public function P2PSitesManager(){
			_siteConns = new Dictionary();
			player = new AudioPlayer();
			player.addEventListener(PlayCompleteEvent.COMPLETE, onComplete);
			player.addEventListener(PlayErrorEvent.PLAY_ERROR, onPlayError);
			player.addEventListener(PlayErrorEvent.ERROR_LOAD_TIMEOUT,onPlayError);
			player.addEventListener(PlayErrorEvent.ERROR_BUFFERING,onPlayError);
			player.addEventListener(PlayProgressEvent.PLAY_ONPROGRESS, onProgress);
			playList = new ArrayCollection();
			lastListenSiteID = -1;
			isSendingLikeRequest = false;
			dbLoader = new URLLoader();
			initSO();
			ContactManager.getInstance().addEventListener(ContactEvent.GET_NEW_LIST,onGetContacts);
		}
		
		private static var instance:P2PSitesManager;
		public static function getInstance():P2PSitesManager{
			if(instance==null){
				instance = new P2PSitesManager();
			}
			
			return instance;
		}
		
		public function start():void{
			_running = true;
			dispatchEvent(new ChaosSitesEvent(ChaosSitesEvent.LISTEN_START));
		}
		
		public function close():void{
			_running = false;
			if(curSite!=null){
				curSite.close();
			}
			player.stop();
			dispatchEvent(new ChaosSitesEvent(ChaosSitesEvent.LISTEN_CLOSED));
		}
		
		public function like():void{
			sendDouBanLikeRequest(curSong.sid,DBRadio.LIKE);
			playSong.like = true;
			if(curSong!=null && curSite!=null){
				if(curSite.status == P2PFMSiteClient.OPEN){
					curSite.like(curSong);
				}
			}
		}
		
		public function unlike():void{
			sendDouBanLikeRequest(curSong.sid,DBRadio.UNLIKE);
			playSong.like = false;
		}
		
		public function resume():void{
			curSite.synchronizeTrack();
		}
		
		public function pause():void{
			if(player.status == AudioPlayer.PLAY)
				player.pause();
		}
		
		public function nextCollectionSite():void{
			var curIdx:int = _contactsSites.getItemIndex(curSiteID);
			if(curIdx<_contactsSites.length-1){
				listenSite(_contactsSites.getItemAt(curIdx+1) as int);
			}else{
				listenSite(_contactsSites.getItemAt(0) as int);
			}
		}
		
		public function set volumn(value:Number):void{
			player.volume = value;
		}
		
		public function get volumn():Number{
			return player.volume;
		}
		
		public function get running():Boolean{
			return _running;
		}
		
		public function listenSite(siteID:int=-1):void{
			//如果SiteID无效，则维持上一个site不变
			if(siteID >0){
				lastListenSiteID = siteID;
				so.data.lastListenSiteID = lastListenSiteID.toString();
				so.flush();
			}
			
			if(this.running==false){
				start();
			}else{
				if(lastListenSiteID!=curSiteID){
					if(curSite!=null){
						curSite.close();
					}
					
					if(player.status == AudioPlayer.PLAY){
						player.stop();
						playList = new ArrayCollection();
					}
					
					if(_siteConns[lastListenSiteID]==null){
						curSite = addNewSiteConn(lastListenSiteID);
					}else{
						curSite = (_siteConns[lastListenSiteID] as P2PFMSiteClient);
					}
					
					_curSiteID = lastListenSiteID;
				}
				
				curSite.listen();
			}
		}
		
		
		
		public function get curSiteName():String{
			if(curSite!=null){
				return curSite.siteName;
			}else{
				return "";
			}
		}
		
		public function get curSiteID():int{
			return _curSiteID;
		}
		
		public function addNewSiteCollection(siteID:int):void{
			if(_contactsSites.source.indexOf(siteID)<0){
				_contactsSites.addItem(siteID);
			}
		}
		
		public function removeSiteCollection(siteID:int):void{
			var idx:int = _contactsSites.getItemIndex(siteID);
			if(idx>=0){
				_contactsSites.removeItemAt(idx);
			}
		}
		
		public function get playSong():TrackInfo{
			return curSong;
		}
		
		private function addNewSiteConn(siteID:int):P2PFMSiteClient{
			var newConn:P2PFMSiteClient = new P2PFMSiteClient(siteID.toString());
			newConn.setOwnerInfo(ContactManager.getInstance().getContactInfo(siteID));
			_siteConns[siteID] = newConn;
			newConn.addEventListener(P2pEvent.CONNECT_SITE_SUCCESSFUL,onConnectSite);
			newConn.addEventListener(P2pEvent.CONNECT_SITE_FAILED,onConnectSiteFailed);
			newConn.addEventListener(P2pEvent.CONNECT_SITE_TIMEOUT,onConnectSiteTimeout);
			newConn.addEventListener(P2pOffLineEvent.NEW_LIST_GOTTEN,onNewOfflineListArrived);
			newConn.addEventListener(P2pEvent.SITE_STARTUP,onSiteStartup);
			newConn.addEventListener(P2pEvent.SITE_CLOSED,onSiteClosed);
			
			return newConn;
		}
		
		private function initSO():void{
			so = SharedObject.getLocal("douchaos","/");
			
			if(so.data.lastListenSiteID!=null){
				lastListenSiteID = parseInt(so.data.lastListenSiteID as String);
			}else{
				so.data.lastListenSiteID = lastListenSiteID.toString();
				so.flush();
			}
			
		}
		
		private function initFriendSites():void{
			var list:ArrayCollection = ContactManager.getInstance().contacts;
			for each(var contactItem:UserInfo in list){
				addNewSiteCollection(contactItem.dbID);
			}
			
			
			if(_contactsSites.length>0 && (lastListenSiteID==-1 || lastListenSiteID==0)){
				lastListenSiteID = _contactsSites.getItemAt(0) as int;
				so.data.lastListenSiteID = lastListenSiteID.toString();
				so.flush();
			}
			
		}
		
		private function onConnectSite(e:P2pEvent):void{
			var targetSite:P2PFMSiteClient = e.currentTarget as P2PFMSiteClient;
			if(running==true){
				if(targetSite==curSite){
					targetSite.addEventListener(P2pEvent.NEW_TRACK_ARRIVED,onNewTrackArrived);
					dispatchEvent(new ChaosSitesEvent(ChaosSitesEvent.SITE_CONNECTED,curSiteID));
					ChaosLogPanel.getInstance().addTempBasicInfo(targetSite.siteName+"连接成功，召唤站长中～");
				}
			}
			setTimeout(checkSiteOpen,3000,targetSite.siteID);
		}
		
		private function onConnectSiteFailed(e:P2pEvent):void{
			var targetSite:P2PFMSiteClient = e.currentTarget as P2PFMSiteClient;
			if(running){
				if(curSite!=null && targetSite==curSite){
					dispatchEvent(new ChaosSitesEvent(ChaosSitesEvent.START_LISTEN_OFFLINE,curSiteID));
					curSite.listenOffline();
				}
			}
			dispatchEvent(new P2pEvent(P2pEvent.FRIEND_SITE_NOT_ON_AIR,targetSite.siteID));
		}
		
		private function onConnectSiteTimeout(e:P2pEvent):void{
			var targetSite:P2PFMSiteClient = e.currentTarget as P2PFMSiteClient;
			if(running){
				if(curSite!=null && targetSite==curSite){
					ChaosLogPanel.getInstance().addBasicInfo(targetSite.siteName+"连接超时");
				}
			}
			dispatchEvent(new P2pEvent(P2pEvent.FRIEND_SITE_NOT_ON_AIR,targetSite.siteID));
		}
		
		private function onSiteStartup(e:P2pEvent):void{
			var targetSite:P2PFMSiteClient = e.currentTarget as P2PFMSiteClient;
			if(running){
				if(curSite!=null && curSite.siteID == targetSite.siteID){
					dispatchEvent(new ChaosSitesEvent(ChaosSitesEvent.SITE_STARTUP,curSiteID));
					ChaosLogPanel.getInstance().addBasicInfo(targetSite.siteName+"开始播送啦");
				}
			}
			dispatchEvent(new P2pEvent(P2pEvent.FRIEND_SITE_ON_AIR,targetSite.siteID));
		}
		
		private function onSiteClosed(e:P2pEvent):void{
			var targetSite:P2PFMSiteClient = e.currentTarget as P2PFMSiteClient;
			if(running){
				if(curSite!=null && curSite.siteID == targetSite.siteID){
					player.stop();
					dispatchEvent(new ChaosSitesEvent(ChaosSitesEvent.SITE_CLOSED));
					if(curSite!=null)
						curSite.listenOffline();
				}
			}
			dispatchEvent(new P2pEvent(P2pEvent.FRIEND_SITE_NOT_ON_AIR,targetSite.siteID));
		}
		
		private function checkSiteOpen(siteID:int):void{
			if(running==true){
				if(curSite!=null && curSite.siteID == siteID){
					if(curSite.status != P2PFMSiteClient.OPEN){
						curSite.listenOffline();
					}
				}
			}
			if((_siteConns[siteID] as P2PFMSiteClient).status != P2PFMSiteClient.OPEN){
				dispatchEvent(new P2pEvent(P2pEvent.FRIEND_SITE_NOT_ON_AIR,siteID));
			}
		}
		
		private function onNewOfflineListArrived(e:P2pOffLineEvent):void{
			if(running){
				var site:P2PFMSiteClient = e.currentTarget as P2PFMSiteClient;
				if(site.siteName == curSite.siteName && site.status == P2PFMSiteClient.LISTEN_OFFLINE){
					playList = new ArrayCollection();
					var track:TrackInfo = site.nextTrack();
					if(track!=null){
						playList.addItem(track);
						
						if(player.status == AudioPlayer.STOP){
							playNextTrack();
						}
					}
				}
			}
		}
		
		private function onNewTrackArrived(e:P2pEvent):void{
			var targetSite:P2PFMSiteClient = e.currentTarget as P2PFMSiteClient;
			if(running){
				if(curSite!=null && curSite.siteID==targetSite.siteID){
					playList = new ArrayCollection();
					playList.addItem(e.data);
					playNextTrack();
				}
			}
		}
		
		private function onComplete(e:PlayCompleteEvent):void
		{
			if(playList.length>0){
				playNextTrack();
			}else{
				if(curSite!=null && curSite.status == P2PFMSiteClient.LISTEN_OFFLINE){
					var track:TrackInfo = curSite.nextTrack();
					if(track!=null){
						playList.addItem(track);
						playNextTrack();
					}
				}else{
					ChaosLogPanel.getInstance().addBasicInfo("等下站长嘛~");
				}
			}
			
		}
		
		private function onProgress(e:PlayProgressEvent):void
		{
			dispatchEvent(new PlayProgressEvent(e.progress));
		}
		
		private function checkPlayListLenValidate():Boolean{
			return playList.length >= 0;
		}
		
		private function playNextTrack():void{
			player.stop();
			if (checkPlayListLenValidate()){
				curSong = playList.source.shift() as TrackInfo;
				dispatchEvent(new ChaosSitesEvent(ChaosSitesEvent.START_PLAY_NEW_TRACK));
				var playType:int;
				if(curSong.subtype!=TrackInfo.LOCAL){
					playType = AudioPlayer.TYPE_DOUBAN;
				}else{
					playType = AudioPlayer.TYPE_LOCAL;
				}
				player.play(curSong.listenURL,playType,curSong.length);
			}
		}
		
		private function onPlayError(e:PlayErrorEvent):void
		{
			switch(e.error)
			{
				case PlayErrorEvent.ERROR_IOERROR:
				{
					if (playList.length <= 0)
					{
						ChaosLogPanel.getInstance().addBasicInfo("等下站长嘛~");
						logger.logError("p2p play io err:" + player.url);
					}else{
						playNextTrack();
					}
					break;
				}
				case PlayErrorEvent.ERROR_LOAD_TIMEOUT:
				{
					ChaosLogPanel.getInstance().addTempBasicInfo(curSong.name+"加载超时...");
					logger.logError("time_out " + player.url, curSong.name,curSong.sid);
					if (playList.length <= 1)
					{
						ChaosLogPanel.getInstance().addBasicInfo("等下站长嘛~");
						logger.logError("p2p listen load time out " + player.url);
					}else
						playNextTrack();
					break;
				}
				case PlayErrorEvent.ERROR_BUFFERING:
				{
					logger.logError("play_slow " + player.url, "ra008");
					ChaosLogPanel.getInstance().addTempBasicInfo("正在缓冲...");
				}
				default:
					break;
			}
		}
		
		private function sendDouBanLikeRequest(sid:int,type:String):void{
			var requrl:String =  Format.radioListURL() + "&type=" + type + 
				 ("&sid=" + (sid==0?"null":sid.toString()))+ "&h=&channel=0";
			try
			{
				dbLoader.close();
			}
			catch (e:Error)
			{
			}
			dbLoader.load(new URLRequest(requrl));
		}
		
		private function onGetContacts(e:ContactEvent):void{
			if(_running==false){
				if(_contactsSites==null){
					_contactsSites = new ArrayCollection();
				}
				initFriendSites();
				tryFriendsSitesOpen();
			}
		}
		
		private function tryFriendsSitesOpen():void{
			var site:P2PFMSiteClient;
			for each(var contactID:int in _contactsSites){
				if(_siteConns[contactID]==null){
					site = addNewSiteConn(contactID);
				}else{
					site = (_siteConns[contactID] as P2PFMSiteClient);
				}
				site.tryOpenP2p();
			}
		}
	}
}